﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if NET

using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils.Extensions;

namespace Microsoft.DotNet.Cli.Utils;

/// <summary>
/// A class which encapsulates logic needed to forward arguments from the current process to another process
/// invoked with the dotnet.exe host.
/// </summary>
internal class ForwardingAppImplementation
{
    private readonly string _forwardApplicationPath;
    private readonly IEnumerable<string> _argsToForward;
    private readonly string? _depsFile;
    private readonly string? _runtimeConfig;
    private readonly string? _additionalProbingPath;
    private Dictionary<string, string> _environmentVariables;

    private readonly string[] _allArgs;

    public ForwardingAppImplementation(
        string forwardApplicationPath,
        IEnumerable<string> argsToForward,
        string? depsFile = null,
        string? runtimeConfig = null,
        string? additionalProbingPath = null,
        Dictionary<string, string>? environmentVariables = null)
    {
        _forwardApplicationPath = forwardApplicationPath;
        _argsToForward = argsToForward;
        _depsFile = depsFile;
        _runtimeConfig = runtimeConfig;
        _additionalProbingPath = additionalProbingPath;
        _environmentVariables = environmentVariables ?? [];

        List<string> allArgs = ["exec"];

        if (_depsFile != null)
        {
            allArgs.Add("--depsfile");
            allArgs.Add(_depsFile);
        }

        if (_runtimeConfig != null)
        {
            allArgs.Add("--runtimeconfig");
            allArgs.Add(_runtimeConfig);
        }

        if (_additionalProbingPath != null)
        {
            allArgs.Add("--additionalprobingpath");
            allArgs.Add(_additionalProbingPath);
        }

        allArgs.Add(_forwardApplicationPath);
        allArgs.AddRange(_argsToForward);

        _allArgs = allArgs.ToArray();
    }

    public int Execute()
    {
        return GetProcessStartInfo().Execute();
    }

    public ProcessStartInfo GetProcessStartInfo()
    {
        var processInfo = new ProcessStartInfo
        {
            FileName = GetHostExeName(),
            Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_allArgs),
            UseShellExecute = false
        };

        foreach (var entry in _environmentVariables)
        {
            processInfo.Environment[entry.Key] = entry.Value;
        }

        return processInfo;
    }

    public ForwardingAppImplementation WithEnvironmentVariable(string name, string value)
    {
        _environmentVariables.Add(name, value);

        return this;
    }

    private string GetHostExeName() => new Muxer().MuxerPath;
}

#endif
